package win.smartown.android.library.certificateCamera;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.blankj.utilcode.util.SPUtils;
import com.blankj.utilcode.util.ToastUtils;
import com.google.gson.Gson;
import com.kaopiz.kprogresshud.KProgressHUD;
import com.orhanobut.dialogplus.DialogPlus;
import com.orhanobut.dialogplus.OnCancelListener;
import com.orhanobut.dialogplus.OnItemClickListener;
import com.orhanobut.dialogplus.ViewHolder;

import org.json.JSONException;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import win.smartown.android.library.certificateCamera.detection.FaceDetectResult;
import win.smartown.android.library.certificateCamera.detection.FaceModel;
import win.smartown.android.library.certificateCamera.detection.ScanResult;

/**
 * Created by smartown on 2018/2/24 11:46.
 * <br>
 * Desc:
 * <br>
 * 拍照界面
 */
public class CameraFaceDetectActivity extends Activity implements View.OnClickListener {

    /**
     * 拍摄类型-身份证正面
     */
    public final static int TYPE_IDCARD_FRONT = 1;
    /**
     * 拍摄类型-身份证反面
     */
    public final static int TYPE_IDCARD_BACK = 2;
    /**
     * 拍摄类型-竖版营业执照
     */
    public final static int TYPE_COMPANY_PORTRAIT = 3;
    /**
     * 拍摄类型-横版营业执照
     */
    public final static int TYPE_COMPANY_LANDSCAPE = 4;

    public final static int RESULT_CODE = 0X14;
    public final static int SCAN_TIP = 1000;
    public final static int SCAN_RESULT = 1001;
    public final static int SCAN_ERROR = 1002;

    private HandlerThread mCheckMsgThread;
    //使用HandlerThread线程的looper创建的mCheckMsgHandler
    private Handler mCheckMsgHandler;


    //图片压缩率
    private int bmpqulity = 50;

    //一开始忽略的图片数量
    private int ignorenum = 8;

    //是否忽略完毕
    private boolean isignoreend = false;

    //是否对焦完毕
    private boolean isfocusover = false;

    //对焦优化
    //优化对焦的手段
    private boolean usetimeoptifocus = true;
    //对焦优化帧数
    private int allowfocusfnum = 10;

    //当前已经对焦帧数
    private int currentfocusfnum = 0;

    //允许的对焦时间
    private long allowfocustsp = 1500;

    //上一次对焦时间
    private long lastfocustime = 0;

    private String IDCARD = "111";//测试用身份证ID

    boolean isUploadImage = false;
    boolean isFeed = true;
    int feedCount = 0;
    int recognizeCount = 0;//上传次数
    int recognizeErrorCount = 0;//上传失败或失败失败次数

    @SuppressLint("HandlerLeak")
    Handler handler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (isUploadImage) {
                return;
            }
            if (msg.what == SCAN_TIP) {

                ScanResult result = (ScanResult) msg.obj;
                //  模糊：-1，正常：0，偏上：1，偏下：2，偏左：3，偏右：4，偏小：5，偏大:6
                String tip;
                switch (result.status) {
                    case -1:
                        tip = "模糊";
                        break;
                    case 0:
                        tip = "正常";
                        break;
                    default:
                        tip = "模糊";
                        break;
                }
                tv_tip.setText(tip);
                if (result.isSucess == 0) {
                    tv_tip.setText("正在识别，请稍后");
                    //将通过的照片存起来
                    SaveBitmap(result.bitmap);
                    uploadImage(result.bitmap);
                    //  stopPreView();
                } else {
                    tv_tip.setText("未识别到人脸");
                    //对焦一次
                    CamAutoFocus();
                    //照片不合格继续上传照片
                    isFeed = true;
                }
                return;
            }

            if (msg.what == SCAN_RESULT) {

                //清空文字
                tv_tip.setText("");

                FaceDetectResult bean = (FaceDetectResult) msg.obj;
                if (bean.real == 0) {
                    Toast.makeText(CameraFaceDetectActivity.this,
                            "未检测到人脸",
                            Toast.LENGTH_SHORT).show();
                    // startScan();
                    //上传结果失败继续喂
                    isFeed = true;
                    //对焦一次
                    CamAutoFocus();
                    return;
                } else {
                    //上传结果成功
                    if(bean.matched==1 ){
                        stopPreView();
                        popResultWindow("人脸身份证匹配成功");
                    }else{
                        ToastUtils.showLong("检测到人脸，但与身份证匹配失败");
                        isFeed=true;
                    }

                }
                //允许继续上传
                isUploadImage = false;
                return;
            }
            if (msg.what == SCAN_ERROR) {
                Toast.makeText(CameraFaceDetectActivity.this,
                        (String) msg.obj + "上传错误:", Toast.LENGTH_SHORT).show();
                isUploadImage = false;
                isFeed = true;
                return;
            }
        }
    };


    //摄像头对焦
    public void CamAutoFocus() {
        isfocusover = false;
        currentfocusfnum = allowfocusfnum;
        lastfocustime = System.currentTimeMillis();
        Log.e("mylog", "focusstart");
        // tv_tip.setText("对焦中");
        cameraPreview.focus();
    }

    //保存文件
    private void SaveBitmap(final Bitmap savebitmap) {
        try {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    String mydir = dir + "/Ok/";
                    try {
                        if (!new File(mydir).exists()) {
                            new File(mydir).mkdir();
                        }
                        final File myfile = new File(mydir + "photo" + System.currentTimeMillis() + ".jpg");
                        myfile.createNewFile();
                        FileOutputStream outstream = new FileOutputStream(myfile);
                        savebitmap.compress(Bitmap.CompressFormat.JPEG, bmpqulity, outstream);
                        outstream.flush();
                        outstream.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    private void popResultWindow(String idCardInfo) {
        ViewHolder viewHolder = new ViewHolder(R.layout.layout_dialog);


        DialogPlus dialog = DialogPlus.newDialog(this)

                .setOnItemClickListener(new OnItemClickListener() {
                    @Override
                    public void onItemClick(DialogPlus dialog, Object item, View view, int position) {
                        Log.e("xiong", "onItemClick");
                    }
                })
                .setOnCancelListener(new OnCancelListener() {
                    @Override
                    public void onCancel(DialogPlus dialog) {
                        Log.e("xiong", "setOnCancelListener");
                        startScan();
                    }
                })
                .setContentHolder(viewHolder)
                .setExpanded(true)  // This will enable the expand feature, (similar to android L share dialog)
                .create();

        TextView textView = (TextView) dialog.findViewById(R.id.txt);

        textView.setText(idCardInfo);
        dialog.show();
    }


    private void stopPreView() {
        isFeed = false;
        scan = false;
        cameraPreview.stopPreview();
    }

    private void startScan() {
        recognizeCount = 0;
        feedCount = 0;
        recognizeErrorCount = 0;
        scan = true;
        isFeed = true;
        cameraPreview.startPreview();

    }


    private CameraPreview cameraPreview;
    private ImageView cropView;
    private Bitmap temp;
    private TextView tv_tip;
    private ExecutorService threadPoolExecutor = Executors.newSingleThreadExecutor();
    FaceModel faceModel;
    int type;
    boolean scan = true;
    KProgressHUD hud;
    OkHttpUpUtil okHttpUpUtil = new OkHttpUpUtil();
    String dir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/ocr/";

    private void initProgress() {
        hud = KProgressHUD.create(this)
                .setStyle(KProgressHUD.Style.SPIN_INDETERMINATE)
                .setLabel("Please wait")
                .setCancellable(false);
    }


    private void recognize(Bitmap bitmap) {
        feedCount++;
        isFeed = false;
        temp = bitmap;

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                ScanResult scanResult = new ScanResult();
                scanResult.bitmap = temp;
                ScanResult result = faceModel.detect(scanResult);
                Message msg = handler.obtainMessage();
                msg.obj = result;
                msg.what = SCAN_TIP;
                handler.sendMessage(msg);
            }
        };
        threadPoolExecutor.execute(runnable);
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        IDCARD = SPUtils.getInstance().getString("idcard","111");

        faceModel = FaceModel.create(getAssets());
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        setContentView(R.layout.activity_face_camera);
        initProgress();
        cameraPreview = (CameraPreview) findViewById(R.id.camera_surface);
        tv_tip = findViewById(R.id.tv_tip);
        cropView = (ImageView) findViewById(R.id.camera_crop);
        cameraPreview.setOnClickListener(this);
        cameraPreview.setOnFrameListener(new CameraPreview.onFrame() {
            @Override
            public void onBitmap(final Bitmap bitmap) {

                if(ignorenum>0) {
                    // tv_tip.setText("倒数中");
                    ignorenum--;
                    if(ignorenum==0) {
                        isignoreend=true;
                        //执行一次对焦
                        CamAutoFocus();
                    }
                }
                //对焦优化
                if(!isfocusover) {
                    if(usetimeoptifocus) {
                        long currenttime=System.currentTimeMillis();
                        Log.e("mytimelog", "lastfocustime:"+lastfocustime);
                        Log.e("mytimelog", "currenttime:"+currenttime);
                        long timesp=currenttime-lastfocustime;
                        Log.e("mytimelog", "timesp:"+timesp);
                        if(timesp>allowfocustsp){
                            //强行二次对焦
                            CamAutoFocus();
                        }
                    }
                    else {
                        currentfocusfnum--;
                        if(currentfocusfnum==0){
                            //强行二次对焦
                            CamAutoFocus();
                        }
                    }
                }
                if (isFeed&&isignoreend&&isfocusover) {
                    tv_tip.setText(tv_tip.getText()+" 图片验证中");
                    recognize(bitmap);
                }
            }
        });
        //对焦成功
        cameraPreview.setonFocusSuccessListener(new CameraPreview.onFocusSuccess() {
            @Override
            public void onFocusSuccess() {

                Log.e("mylog", "focusend");
                isfocusover = true;
            }
        });

        setScanFrameSize(428, 270);

    }


    private void uploadImage(final Bitmap bitmap) {
        isUploadImage = true;
        recognizeCount++;

        try {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        if (!new File(dir).exists()) {
                            new File(dir).mkdir();
                        }
                        final File file = new File(dir + "photo" + System.currentTimeMillis() + ".jpg");
                        file.createNewFile();
                        Log.e("xiong", file.getAbsolutePath());
                        FileOutputStream out = new FileOutputStream(file);
                        bitmap.compress(Bitmap.CompressFormat.JPEG, bmpqulity, out);
                        out.flush();
                        out.close();
                        final String uploadurl = "http://192.168.17.58:8383/sfz";
                        String result = okHttpUpUtil.uploadImage(uploadurl, file.getAbsolutePath(), IDCARD);
                        isUploadImage = false;
                        Log.e("xiong", "****************" + result);
                        Gson gson = new Gson();
                        FaceDetectResult faceBean = gson.fromJson(result, FaceDetectResult.class);
                        Message msg = handler.obtainMessage();
                        msg.what = SCAN_RESULT;
                        msg.obj = faceBean;
                        handler.sendMessage(msg);
                    } catch (IOException | JSONException e) {
                        Log.e("xiong", "-----------------++++++++" + e.getMessage());
                        isUploadImage = false;
                        Message msg = handler.obtainMessage();
                        msg.what = SCAN_ERROR;
                        msg.obj = e.getMessage();
                        handler.sendMessage(msg);
                        e.printStackTrace();
                    }
                }
            }).start();

        } catch (Exception e) {
            Log.e("xiong", e.getMessage());
            Message msg = handler.obtainMessage();
            msg.what = SCAN_ERROR;
            msg.obj = e.getMessage();
            handler.sendMessage(msg);
            Log.e("xiong", e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
     */
    public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }


    public void setScanFrameSize(int width, int height) {
        LinearLayout.LayoutParams cropParams = new LinearLayout.LayoutParams(dip2px(this, width), dip2px(this, height));
        cropView.setLayoutParams(cropParams);
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.camera_surface) {
            CamAutoFocus();
        } else if (id == R.id.camera_close) {
            finish();
        } else if (id == R.id.camera_take) {
            //takePhoto();
        } else if (id == R.id.camera_flash) {
            boolean isFlashOn = cameraPreview.switchFlashLight();
            // flashImageView.setImageResource(isFlashOn ? R.mipmap.camera_flash_on : R.mipmap.camera_flash_off);
        } else if (id == R.id.camera_result_ok) {
            goBack();
        } else if (id == R.id.camera_result_cancel) {
            //  optionView.setVisibility(View.VISIBLE);
            cameraPreview.setEnabled(true);
            //  resultView.setVisibility(View.GONE);
            cameraPreview.startPreview();
        }
    }


    /**
     * @return 拍摄图片裁剪文件
     */
    private File getCropFile() {
        switch (type) {
            case TYPE_IDCARD_FRONT:
                return new File(getExternalCacheDir(), "idCardFrontCrop.jpg");
            case TYPE_IDCARD_BACK:
                return new File(getExternalCacheDir(), "idCardBackCrop.jpg");
            case TYPE_COMPANY_PORTRAIT:
            case TYPE_COMPANY_LANDSCAPE:
                return new File(getExternalCacheDir(), "companyInfoCrop.jpg");
        }
        return new File(getExternalCacheDir(), "pictureCrop.jpg");
    }

    /**
     * 点击对勾，使用拍照结果，返回对应图片路径
     */
    private void goBack() {
        Intent intent = new Intent();
        intent.putExtra("result", getCropFile().getPath());
        setResult(RESULT_CODE, intent);
        finish();
    }

}
